Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Salve a tutti, ho questo problema in un'applicazione .NET. Ho bisogno di catturare l'output di un processo, sia ciò che viene scritto sullo standard output che sullo standard error; per ora, in particolare, sono interessato all'output del compilatore java (javac.exe, che in realtà scrive tutto su stderr, ma vorrei una soluzione "pulita" in modo che in futuro possa riutilizzare il codice per altri comandi che mandano alcuni messaggi di output su stdout e altri su stderr). In altre parole, ho bisogno di leggere in tempo reale stdout e stderr man mano che vengono scritti dal processo e nell'ordine giusto (ovvero non prima tutto stdout e poi tutto stderr o viceversa), esattamente come vengono mostrati quando il processo viene lanciato da terminale.
Detto questo, il codice che sono riuscito a scrivere è questo.
Codice sorgente - presumibilmente VB.NET
DelegateSub onOutputDelegate(ByVal output AsString, ByValisErrorAsBoolean)'funzione che verrà chiamata ogni volta che il processo scrive qualcosa in uno dei due flussi di output
If cwd <> ""Then p.StartInfo.WorkingDirectory= cwd
p.Start()
Dim thOut AsNew Thread(Sub()
WhileNot p.HasExited
onOutput(p.StandardOutput.ReadLine(), False)
EndWhile
EndSub)
Dim thErr AsNew Thread(Sub()
WhileNot p.HasExited
onOutput(p.StandardError.ReadLine(), True)
EndWhile
EndSub)
thOut.Start()
thErr.Start()
p.WaitForExit()
EndSub
Come potete vedere la soluzione che mi è venuta in mente è di lanciare contemporaneamente due thread separati, uno per stdout e uno per stderr.
Inizialmente sembrava funzionare tutto, ma poi mi sono accorto di un comportamento strano: a volte certe righe di output non vengono lette, mente altre volte si (lanciando lo stesso identico comando con gli stessi parametri), in maniera apparentemente casuale.
Qualcuno saprebbe aiutarmi? Inoltre, secondo voi la soluzione dei due thread vi sembra una buona idea o ci sono alternative migliori? Grazie in anticipo a chiunque risponderà
Il probelma è che così leggi solo lo Standard Output, io invece, come avevo specificato, ho bisogno di leggere contemporaneamente Standard Output e Standard Error... Grazie comunque
Postato originariamente da vankraster: Perché ti serve leggere i dati contemporaneamente? Forse troviamo un'altra soluzione.
Ti spiego, sto programmando un IDE che deve lanciare dei compilatori e mostrarne e parsarne l'output (in modo da mostrare una lista di errori presenti nel codice), attualmente sono al lavoro con il compilatore java ma vorrei generalizzare il codice per l'avvio di un processo e la lettura del rispettivo output in modo da poterlo riutilizzare se e quando ne supporterò altri; vorrei quindi riuscire a ricevere sia l'stdout che l'stderr in modo che su qualsiasi di questi flussi scriva il programma che lancio, l'output venga mostrato all'utente nel mio programma.
Usando ReadToEnd ho parzialmente risolto in questo modo, dovendo però rinunciare ella lettura in tempo reale:
Codice sorgente - presumibilmente VB.NET
p.Start()
p.WaitForExit()
Dim out AsString= p.StandardOutput.ReadToEnd()
ForEach l AsString In out.Split(Environment.NewLine)
ForEach l AsString In err.Split(Environment.NewLine)
onOutput(l, True)
Next
E così funziona, anche se ovviamente l'output arriva solo quando il processo è terminato e non in ordine (prima tutto stdout e poi tutto stderr). Possibile che non sia possibile monitorare entrambi gli stream e leggerli riga per riga man mano che il processo li scrive? E' una settimana ormai che ci sto sbattendo la testa
P.S. ho provato anche con gli eventi OutputDataReceived e ErrorDataReceived, in questo modo:
Codice sorgente - presumibilmente VB.NET
AddHandler p.OutputDataReceived, Sub(sender AsObject, e As DataReceivedEventArgs)
onOutput(e.Data, False)
EndSub
p.BeginOutputReadLine()
AddHandler p.ErrorDataReceived, Sub(sender AsObject, e As DataReceivedEventArgs)